﻿using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using IceMan.Domain;
using System.Diagnostics.CodeAnalysis;

namespace IceMan.Shared
{
    public partial class IceMain
    {
        [Inject]
        [NotNull]
        public IStateStore? stateStore { get; set; }

        [Inject]
        [NotNull]
        public Config? config { get; set; }

        private StateContainer makeFirstStates;
        private StateContainer makeSecondStates;
        private StateContainer replaceMaterialStates;

        public IceMain()
        {
            makeFirstStates = new StateContainer(new List<IMaterialType>
            {
                Strawberry.Default,Chocolates.Default,IceCream.Default
            }, 5, WorkType.Window1);

            makeSecondStates = new StateContainer(new List<IMaterialType>
            {
                 IceCream.Default, Strawberry.Default,Chocolates.Default
            }, 8, WorkType.Window2);

            replaceMaterialStates = new StateContainer(new List<IMaterialType>
            {
                IceCream.Default , Strawberry.Default , Chocolates.Default
            }, 5, WorkType.ReplaceMaterial);
        }
        protected override void OnInitialized()
        {
            base.OnInitialized();

            InitState();
        }
        private void InitState()
        {
            try
            {
                MainState = stateStore.Load();

                MainState.InitRef(config, stateStore);

                MainState.InitStateByLog(makeFirstStates, makeSecondStates, replaceMaterialStates);
            }
            catch (Exception ex)
            {
            }

        }

        public MainState MainState { get; private set; }
        /// <summary>
        /// 切换到下一个状态 成功时，使用此方法更新页面状态并记录修改日志
        /// </summary>
        /// <param name="stateContainer"></param>
        /// <exception cref="InvalidOperationException"></exception>
        private async ValueTask NextStateAction(StateContainer stateContainer)
        {
            // 记录步骤完成日志
            switch (stateContainer.WorkType)
            {
                case WorkType.Window1:
                    await stateContainer.DoWork();
                    if (!stateContainer.IsInitState)
                    {
                        MainState.AddWindow_1Log(stateContainer.CurrentState, false);
                    }
                    break;
                case WorkType.Window2:
                    await stateContainer.DoWork();
                    if (!stateContainer.IsInitState)
                    {
                        MainState.AddWindow_2Log(stateContainer.CurrentState, false);
                    }

                    break;
                case WorkType.ReplaceMaterial:
                    await stateContainer.DoWork();
                    if (!stateContainer.IsInitState)
                    {
                        MainState.AddReplaceMaterialLog(stateContainer.CurrentState, false);
                    }
                    break;
                default:
                    throw new InvalidOperationException($"当前状态类型无法追加日志{stateContainer.WorkType}");
            }
        }

        private async ValueTask StartNewWork(StateContainer stateContainer)
        {
            var cancelToken = stateContainer.CancellationTokenSource.Token;
            
            while (!cancelToken.IsCancellationRequested && stateContainer.NextState())
            {
                if (cancelToken.IsCancellationRequested)
                {
                    return;
                }

                StateHasChanged();

                await NextStateAction(stateContainer);
            }

            if (cancelToken.IsCancellationRequested)
            {
                return;
            }

            // 添加完成日志
            switch (stateContainer.WorkType)
            {
                case WorkType.Window1:
                    MainState.AddWindow_1Log(null, true);
                    break;
                case WorkType.Window2:
                    MainState.AddWindow_2Log(null, true);
                    break;
                case WorkType.ReplaceMaterial:
                    MainState.AddReplaceMaterialLog(null, true);
                    break;
                default:
                    throw new InvalidOperationException($"当前状态类型无法追加日志{stateContainer.WorkType}");
            }

            StateHasChanged();
        }
        /// <summary>
        /// 进入窗口1制作状态
        /// </summary>
        public async void StartMakeFirst()
        {
            if (makeFirstStates.IsRunning)
            {
                throw new InvalidOperationException("正在窗口1制作中，无法重复进入此状态");
            }

            await StartNewWork(makeFirstStates);
        }
        /// <summary>
        /// 进入窗口2制作状态
        /// </summary>
        public async void StartMakeSecond()
        {
            if (makeSecondStates.IsRunning)
            {
                throw new InvalidOperationException("正在窗口2制作中，无法重复进入此状态");
            }

            await StartNewWork(makeSecondStates);
        }

        /// <summary>
        /// 进入更换材料状态
        /// </summary>
        public async void StartReplaceMaterial()
        {
            if (replaceMaterialStates.IsRunning)
            {
                throw new InvalidOperationException("正在更换材料，无法重复进入此状态");
            }

            await StartNewWork(replaceMaterialStates);
        }

        void ExecuteCancelWindow1()
        {
            makeFirstStates.ResetInitState();
            MainState.AddWindow_1Log(null, true);
        }

        void ExecuteCancelWindow2()
        {
            makeSecondStates.ResetInitState();
            MainState.AddWindow_2Log(null, true);
        }

        void ExecuteCancelReplaceMaterial()
        {
            replaceMaterialStates.ResetInitState();
            MainState.AddReplaceMaterialLog(null, true);
        }

        bool CanExecuteMakeFirst()
        {
            // 材料充足，且当前窗口不在运行状态
            return !replaceMaterialStates.IsRunning && !makeFirstStates.IsRunning && IsMaterialEnough;
        }

        bool CanExecuteMakeSecond()
        {
            // 材料充足，且当前窗口不在运行状态
            return !replaceMaterialStates.IsRunning && !makeSecondStates.IsRunning && IsMaterialEnough;
        }

        bool CanExecuteReplaceMaterial()
        {
            // 两个窗口都没有运行，则可以更换材料
            return !replaceMaterialStates.IsRunning && !makeSecondStates.IsRunning && !makeFirstStates.IsRunning;
        }
        public bool IsMaterialEnough => MainState.MaterialCount > 0;
    }
}
